spec: a figure group's panels nest directly, and the wrapper div goes - #1241
Merged
Conversation
HTML's figure content model is a figcaption first or last plus flow content, and figure is itself flow content, so the panel figures are exactly what the group element admits - the intermediate div.carve-figure-panels added nothing the markup needed and is dropped from PART 9 section 4c's shape, the oracle, and the nine corpus cases that emit a group. This is also the shape Pandoc's writers produce for native subfigures, which keeps HTML import and export symmetric with the bridge. The wrapper was the initial draft shape and is revised before any release, so no shipped document ever carried it. Zero-panel groups hold their preserved content directly; a consumer selects panels by the carve-figure-panel class, never by position. The pinned engine still emits the wrapper, so the affected slugs are declared in the engine-pin-drift file until the engine updates land and the pin moves.
dereuromark
added a commit
to markup-carve/carve-php
that referenced
this pull request
Aug 16, 2026
PART 9 section 4c revision (markup-carve/carve#1122), ruled before any release carries the shape. The `<div class="carve-figure-panels">` wrapper is gone: panels and preserved stray content nest DIRECTLY inside `<figure class="carve-figure-group">`, one indent level up, with the group's `<figcaption>` last and `carve-figure-panel` unchanged on each panel. HTML's content model for `figure` is one `figcaption` first-or-last plus flow content, and a `figure` is itself flow content - so the wrapper drew a box the element already provides, and a consumer styling the group can select `.carve-figure-group > .carve-figure-panel` exactly as it could select the div. Pandoc's subfigure HTML output has the same flat shape, which the sibling engines match byte for byte through the shared corpus. The HTML importer reads the flat shape back: panels are the direct `figure.carve-figure-panel` children of the group and the group caption is the direct `figcaption` child - a panel's own caption sits inside the panel figure, so the direct-child scan never confuses the two. An empty uncaptioned group keeps the bare-container empty-body form - the PART 10 section 4 exception the bare div takes, and the shape the oracle emits. The tests/spec submodule pin moves to 427b125 on spec main, the merged markup-carve/carve#1241, whose corpus pins the flat bytes; all eleven 318-composite-figures documents pass byte for byte.
dereuromark
added a commit
to markup-carve/carve-php
that referenced
this pull request
Aug 16, 2026
PART 9 section 4c revision (markup-carve/carve#1122), ruled before any release carries the shape. The `<div class="carve-figure-panels">` wrapper is gone: panels and preserved stray content nest DIRECTLY inside `<figure class="carve-figure-group">`, one indent level up, with the group's `<figcaption>` last and `carve-figure-panel` unchanged on each panel. HTML's content model for `figure` is one `figcaption` first-or-last plus flow content, and a `figure` is itself flow content - so the wrapper drew a box the element already provides, and a consumer styling the group can select `.carve-figure-group > .carve-figure-panel` exactly as it could select the div. Pandoc's subfigure HTML output has the same flat shape, which the sibling engines match byte for byte through the shared corpus. The HTML importer reads the flat shape back: panels are the direct `figure.carve-figure-panel` children of the group and the group caption is the direct `figcaption` child - a panel's own caption sits inside the panel figure, so the direct-child scan never confuses the two. An empty uncaptioned group keeps the bare-container empty-body form - the PART 10 section 4 exception the bare div takes, and the shape the oracle emits. The tests/spec submodule pin moves to 427b125 on spec main, the merged markup-carve/carve#1241, whose corpus pins the flat bytes; all eleven 318-composite-figures documents pass byte for byte.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #1122 (and #1215): the
<div class="carve-figure-panels">wrapper is dropped from the composite-figure shape. Panels nest directly in the groupfigure.Why
figureholds afigcaptionfirst or last plus arbitrary flow content, andfigureis itself flow content - so nested panel figures are exactly what the element admits. The wrapper added no validity and no structure the markup needed (surfaced by the content-model discussion on jgm/djot#31).What changed
scripts/spec/html.mjs: the oracle emits the flat shape (panels and preserved stray content sit one level up; zero-panel groups hold their content directly; the groupfigcaptionstays last).318-composite-figures,-2,-3,-4,-5,-6,-9,-10,-11.-7and-8are untouched (they emit no group).resources/engine-pin-drift.txt: the pinned carve-js (456ce074) still emits the wrapper, so the nine slugs are declared until the engine updates land and the pin moves. The pin does not move here.